package com.yiji.fintech.musfinance.common.enginerules;

import com.acooly.core.utils.Collections3;
import com.acooly.core.utils.mapper.BeanCopier;
import com.google.common.collect.Lists;
import com.yiji.fintech.musfinance.common.annotation.RuleStrategyAnnotation;
import com.yiji.fintech.musfinance.common.context.SpringApplicationContext;
import com.yiji.fintech.musfinance.common.domain.base.BaseDomain;
import com.yiji.fintech.musfinance.common.domain.channel.ChannelDomain;
import com.yiji.fintech.musfinance.common.domain.channel.InstChannelApiDomain;
import com.yiji.fintech.musfinance.common.enums.StatusEnum;
import com.yiji.fintech.musfinance.common.strategy.base.AbstractRulesStrategy;
import com.yiji.fintech.musfinance.common.utils.BizAssert;
import com.yiji.fintech.musfinance.common.utils.cache.BizCacheService;
import com.yiji.fintech.musfinance.common.utils.cache.CacheConstant;
import com.yiji.fintech.musfinance.entity.BusinessConfig;
import com.yiji.fintech.musfinance.entity.BusinessRule;
import com.yiji.fintech.musfinance.entity.InstChannelApi;
import com.yiji.fintech.musfinance.entity.RouteRule;
import com.yiji.fintech.musfinance.service.BusinessConfigService;
import com.yiji.fintech.musfinance.service.BusinessRuleService;
import com.yiji.fintech.musfinance.service.InstChannelApiService;
import com.yiji.fintech.musfinance.service.RouteRuleService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * 超级路由
 * Created by ouwen@yiji.com} on 2017/9/22.
 */
@Service
public class SuperRouteServiceImpl implements SuperRouteService{
    @Autowired
    private BizCacheService bizCacheService;

    @Override
    public void channel(BaseDomain domain) {
        prepare(domain);//规则预处理
        List<RouteRule> routeRules = load(domain);//加载路由规则
        List<InstChannelApiDomain> instChannelApiDomains = converter(routeRules);
        ChannelDomain channelDomain = new ChannelDomain();//Domain转换ChannelDomain
        BeanCopier.copy(domain,channelDomain,BeanCopier.CopyStrategy.IGNORE_NULL, BeanCopier.NoMatchingRule.IGNORE,null);
        channelDomain.setInstChannelApis(instChannelApiDomains);//设置ChannelDomain加载的规则
        //获取Domain注解上面规则策略服务
        RuleStrategyAnnotation ruleStrategyAnnotation = domain.getClass().getAnnotation(RuleStrategyAnnotation.class);
        Class strategyClass = ruleStrategyAnnotation.strategyClass();
        AbstractRulesStrategy rulesStrategy = (AbstractRulesStrategy)SpringApplicationContext.getBeanByClass(strategyClass);
        rulesStrategy.doExcute(channelDomain,domain);//执行规则策略
    }

    /**
     * 规则预处理
     * @param domain
     */
    private void prepare(BaseDomain domain){
        businessConfig(domain);
        businessRule(domain);
    }

    /**
     * 路由规则转换为渠道信息+路由规则信息
     * @param routeRules
     * @return
     */
    private List<InstChannelApiDomain> converter(List<RouteRule> routeRules){
        List<InstChannelApiDomain> instChannelApiDomains = Lists.newArrayList();
        for(RouteRule routeRule :routeRules){
            InstChannelApiDomain instChannelApiDomain = new InstChannelApiDomain();
            BeanCopier.copy(routeRule,instChannelApiDomain, BeanCopier.CopyStrategy.IGNORE_NULL, BeanCopier.NoMatchingRule.IGNORE,null);
            InstChannelApi channelApiParams = new InstChannelApi();
            channelApiParams.setGatewayChannelApi(routeRule.getGatewayChannelApi());
            List<InstChannelApi> channelApiCaches = bizCacheService.query(CacheConstant.CENTER_INSTCHANNEL_API_MUTICACHE,channelApiParams,InstChannelApiService.class);
            if(Collections3.isEmpty(channelApiCaches)){
                continue;
            }
            InstChannelApi instChannelApi = channelApiCaches.get(0);
            instChannelApiDomain.setGatewayChannelApi(instChannelApi.getGatewayChannelApi());
            instChannelApiDomain.setGatewayChannelApiDesc(instChannelApi.getGatewayChannelApiDesc());
            instChannelApiDomain.setDayQuota(instChannelApi.getDayQuota());
            instChannelApiDomain.setQuota(instChannelApi.getQuota());
            instChannelApiDomain.setRate(instChannelApi.getRate());
            instChannelApiDomains.add(instChannelApiDomain);
        }
        return instChannelApiDomains;
    }
    /**
     * 是否具有业务能力
     * @param domain
     */
    private void businessRule(BaseDomain domain){
        BusinessRule businessRule = new BusinessRule();
        businessRule.setPartnerId(domain.getPartnerId());
        businessRule.setInstBankId(domain.getInstBankId());
        businessRule.setStatus(StatusEnum.ON);
        businessRule.setCardType(domain.getCardType());
        businessRule.setPersonalCorporateType(domain.getPersonalCorporateType());
        businessRule.setTransactionType(domain.getTransactionType());
        businessRule.setSubTransactionType(domain.getSubTransactionType());
        List<BusinessRule> businessRules = bizCacheService.query(CacheConstant.CENTER_BUSINESS_RULE_MUTICACHE,businessRule,BusinessRuleService.class);
        BizAssert.notEmpty(businessRules,"商户【"+domain.getPartnerId()+"】未配置业务能力");
    }
    /**
     * 商户是否接入
     */
    private void businessConfig(BaseDomain domain){
        BusinessConfig bcparmes = new BusinessConfig();
        bcparmes.setPartnerId(domain.getPartnerId());
        bcparmes.setStatus(StatusEnum.ON);
        List<BusinessConfig> businessConfigList = bizCacheService.query(CacheConstant.CENTER_BUSINESS_CONFIG_MUTICACHE,bcparmes,BusinessConfigService.class);
        BizAssert.notEmpty(businessConfigList,"商户【"+domain.getPartnerId()+"】未接入");
        BusinessConfig businessConfig = businessConfigList.get(0);
        domain.setTrustModel(businessConfig.getTrustModel());
    }
    /**
     * 获取路由规则
     * @param domain
     */
    private List<RouteRule> load(BaseDomain domain){
        RouteRule routeRule = new RouteRule();
        routeRule.setPartnerId(domain.getPartnerId());
        routeRule.setInstBankId(domain.getInstBankId());
        routeRule.setStatus(StatusEnum.ON);
        routeRule.setCardType(domain.getCardType());
        routeRule.setPersonalCorporateType(domain.getPersonalCorporateType());
        routeRule.setTransactionType(domain.getTransactionType());
        routeRule.setSubTransactionType(domain.getSubTransactionType());
        routeRule.setElementType(domain.getElementType());
        List<RouteRule> routeRules = bizCacheService.query(CacheConstant.CENTER_ROUTE_RULE_MUTICACHE,routeRule,RouteRuleService.class);
        BizAssert.notEmpty(routeRules,"商户【"+domain.getPartnerId()+"】未配置路由规则");
        return routeRules;
    }
}
